package plus;
import plus.decl.Template;
/**
 * I think the idea is that TEnv collects all the knowledge about how to enter, search,
 * and exit a type interpretation environment. But how can that be, when I'm not even sure
 * the type language is even quite correct?
 * 
 * So the next trick is to make "current" private. I'll bet that will suss out some suds.
 * 
 * @author me
 *
 */
public abstract class TEnv {
	private static TEnv current = null;
	static int foo;
	final TEnv outer;
	TEnv(TEnv outer) { this.outer = outer; }
	public static Symbol<TypeSym> findType(String name) {
		TEnv e = current;
		Symbol<TypeSym> sym = null;
		while (sym == null && e != null) {
			sym = e.getTypeSym(name);
			e = e.outer;
		}
		return sym;
	}
	public static Type find(String name) {
		TEnv e = current;
		Type t = null;
		while (t == null && e != null) {
			t = e.get(name);
			e = e.outer;
		}
		return t;
	}
	protected abstract Type get(String name);
	protected abstract Symbol<TypeSym> getTypeSym(String name);
	public static void exit() { current = current.outer; }
	public static void enterSub() { current = new TEnvSubroutine(current); }
	public static void enterKappa(Template tpl) { current = new Kappa(current, tpl); }
	public abstract void addType(Symbol<TypeSym> sym);
	public static void add(Symbol<TypeSym> sym) { current.addType(sym); }
	public static void define(Template tpl, Type basis) {
		// TODO Auto-generated method stub
		
	}
	static class TEnvSubroutine extends TEnv {
		TEnvSubroutine(TEnv outer) { super(outer); }
		Scope<TypeSym> types = new Scope<TypeSym>();
		@Override protected Symbol<TypeSym> getTypeSym(String name) { return types.find(name); }
		@Override public void addType(Symbol<TypeSym> sym) { types.enter(sym); }
		@Override protected Type get(String name) {
			// TODO Auto-generated method stub
			return null;
		}	
	}
	/**
	 * The purpose of the class "KAPPA" is to act as a type environment for the
	 * interpretation of generic type declarations given via TYPEDEF or RECORD.
	 * Specifically, it maps names to the formal type parameters.
	 * We presume the formal (and thus free) type variables are listed in the
	 * TypeSym while the names are provided in order by the definition.
	 * @author Hubby
	 *
	 */
	static final class Kappa extends TEnv {
		final Symbol<TypeSym>[] syms;
		@SuppressWarnings("unchecked")
		public Kappa(TEnv env, Template tpl) {
			super(env);
			syms = new Symbol[tpl.formals.size()];
			int i=0;
			for (String nm:tpl.formals) {
				syms[i] = new Symbol<TypeSym>(nm, tpl.sym.lineNr, TS_Formal.get(i));
				i++;
			}
		}
		private int _find(String name) {
			for (int i=0; i<syms.length; i++) if (syms[i].name == name) return i;
			return -1;
		}
		@Override public Symbol<TypeSym> getTypeSym(String name) {
			int i=_find(name);
			return i>=0 ? syms[i] : null;
		}
		@Override public void addType(Symbol<TypeSym> sym) { throw null; }
		@Override protected Type get(String name) {
			int i=_find(name);
			//return i>=0 ? syms[i].definition : null;
			return null;
			// TODO this is broken...
		}
	}
}
